/*!
 * The Qwiki Web Player 4.0.0 (2013-02-26, 10:58)
 *
 * Copyright (C) 2013 Qwiki, Inc.
 */
/**
 * The main JS file which is used to define the QWIKI
 * namespace. Must be loaded prior to any other component
 * of the Qwiki HTML5 player or QVG renderer.
 *
 * @author Hakim El Hattab
 */
// Ensure that the main QWIKI object is defined
var QWIKI = QWIKI || {};
QWIKI.initialized === undefined && (QWIKI.initialized = !1),
QWIKI.ns = function(e) {
    e = e.split(".");
    var t = QWIKI;
    while (e.length) {
        var n = e.shift();
        t[n] || (t[n] = {}),
        t = t[n]
    }
    return t
},
QWIKI.initialize = function() {
    window.console = window.console || {},
    window.console.log = window.console.log ||
    function() {},
    window.console.info = window.console.info ||
    function() {},
    window.console.warn = window.console.warn ||
    function() {},
    window.console.error = window.console.error ||
    function() {},
    window.console.group = window.console.group ||
    function() {},
    window.console.groupCollapsed = window.console.groupCollapsed ||
    function() {},
    window.console.groupEnd = window.console.groupEnd ||
    function() {},
    QWIKI.initialized === !1 && (QWIKI.initialized = !0, QWIKI.DEBUG === undefined && QWIKI.io && (QWIKI.DEBUG = QWIKI.io.Query.getValue("debug")), QWIKI.DEBUG && QWIKI.io.Logger.info("Qwiki system initialized (debug level " + QWIKI.DEBUG + ")"), QWIKI.io && QWIKI.io.Settings.init())
},
QWIKI.ns("player.signal"),
QWIKI.player.signal.Advisor = {
    userInteractionRequiredToPlay: function() {
        var e = QWIKI.player.Player.getConfig();
        return this.isTouchDevice() || e.embed && !e.autoplay
    },
    scalePlayerToFit: function() {
        return this.isEmbedded() || this.isFullScreen()
    },
    replay: function() {
        return !! QWIKI.player.Player.getConfiguration().replay
    },
    isFullScreen: function() {
        return !! document.fullScreenElement && document.fullScreenElement !== null || !!document.mozFullScreen || !!document.webkitIsFullScreen
    },
    displayFooterLogo: function() {
        return this.isEmbedded()
    },
    useLowQualityAssets: function() {
        return !! QWIKI.player.Player.getConfiguration().lq
    },
    useFlashMedia: function() {
        return (!QWIKI.player.signal.Advisor.supportsHTMLMedia() || QWIKI.player.Player.getConfig().useflash) && QWIKI.player.signal.Advisor.supportsFlash()
    },
    useAppBanner: function() {
        return ! this.isEmbedded() && !!navigator.userAgent.match(/iphone|ipod/gi)
    },
    supportsFullScreen: function() {
        return ! document.fullscreenEnabled && !document.mozFullScreenEnabled && !document.webkitFullscreenEnabled ? !1 : !0
    },
    supportsFlash: function() {
        return swfobject.hasFlashPlayerVersion("10")
    },
    supportsHTMLMedia: function() {
        return (Modernizr.video.webm || Modernizr.video.h264) && (Modernizr.audio.mp3 || Modernizr.audio.ogg)
    },
    isAppCapableMobile: function() {
        return !! navigator.userAgent.match(/iphone;|ipod;/gi)
    },
    isWebCapableMobile: function() {
        return !! navigator.userAgent.match(/ipad/gi)
    },
    isMobile: function() {
        return !! navigator.userAgent.match(/iphone;|ipod;|ipad|android|blackberry/gi)
    },
    isIOS: function() {
        return !! navigator.userAgent.match(/iphone;|ipod;|ipad/gi)
    },
    isIOS5: function() {
        return this.isIOS() && !!navigator.userAgent.match(/OS\s5_/gi)
    },
    isIOS4: function() {
        return this.isIOS() && !!navigator.userAgent.match(/OS\s4_/gi)
    },
    isAndroid: function() {
        return !! navigator.userAgent.match(/android/gi)
    },
    isTouchDevice: function() {
        return "ontouchstart" in window && this.isMobile()
    },
    isPortrait: function() {
        return window.orientation === 0 ? !0 : !1
    },
    isEmbedded: function() {
        return QWIKI.player.Player.getConfig().embed === !0
    },
    isInDevelopment: function() {
        return QWIKI.ENVIRONMENT === "development"
    }
},
QWIKI.ns("player.signal"),
QWIKI.player.signal.Tracking = function() {
    function e() {
        return window.mixpanel !== undefined
    }
    function t(e, t) {
        t = t || {},
        t.category = "system",
        r(e, t)
    }
    function n(e, t) {
        t = t || {},
        t.category = "ui",
        r(e, t)
    }
    function r(t, n) {
        if (e()) {
            n = n || {},
            n.player_context = QWIKI.player.signal.Advisor.isEmbedded() ? "embedded": "default";
            var r = QWIKI.player.Player.getData();
            r && r.hasUser() && (n.qwiki_owner = r.user.username),
            r && (n.qwiki_title = r.title),
            r && (n.qwiki_token = r.id),
            mixpanel.track("Player: " + t, n)
        }
    }
    return {
        onInitialized: function() {
            t("Initialized")
        },
        onDataLoaded: function() {
            t("Data Loaded")
        },
        onDataFailed: function() {
            t("Data Failed")
        },
        onPlaybackStarted: function() {
            t("Playback Started")
        },
        onPlaybackEnded: function() {
            t("Playback Ended")
        },
        onPlaybackPaused: function() {
            t("Playback Paused")
        },
        onPlaybackResumed: function() {
            t("Playback Resumed")
        },
        onPlaybackRestarted: function() {
            t("Playback Restarted")
        },
        onPlaybackProgress: function(e) {
            t("Playback Progress", {
                progress: e
            })
        },
        onSeeked: function() {
            n("Seeked")
        },
        onSoundtrackClicked: function() {
            n("Clicked: iTunes Soundtrack")
        },
        onFooterLogoClicked: function() {
            n("Clicked: Footer Logo")
        },
        onEmbedClicked: function() {
            n("Clicked: Embed ")
        },
        onMuteClicked: function(e) {
            n("Clicked: Mute ", {
                turned_on: e
            })
        },
        onFullScreenClicked: function(e) {
            n("Clicked: FullScreen", {
                turned_on: e
            })
        }
    }
} (),
QWIKI.ns("player.signal"),
QWIKI.player.signal.ErrorHandler = {
    init: function() {
        window.onQwikiMediaPlayerError = function(e, t) {
            this.mediaPlayerFailed.dispatch(e, t),
            QWIKI.warn("onQwikiMediaPlayerError: " + t + "(" + e + ")")
        }.bind(this),
        this.mediaPlayerFailed = new signals.Signal
    },
    report: function(e, t) {
        var n = "";
        for (var r in QWIKI.player.data.types.ErrorCodes) if (QWIKI.player.data.types.ErrorCodes[r] === e) {
            n = r;
            break
        }
        var i = "#" + e + " " + n;
        typeof t == "string" ? i += " (" + t + ")": typeof t == "object" && (i += " " + JSON.stringify(t)),
        e > QWIKI.player.data.types.ErrorCodes.ERRORS ? QWIKI.logger.error("Error " + i) : e > QWIKI.player.data.types.ErrorCodes.WARNINGS && QWIKI.logger.warn("Warning " + i),
        this.takeAction(e)
    },
    takeAction: function(e, t) {
        switch (e) {
        case QWIKI.player.data.types.ErrorCodes.QWIKI_NOT_FOUND:
            QWIKI.player.Player.crash('<h2>Qwiki Not Found</h2><p>The author may have removed it.<br><a href="http://www.qwiki.com/">Click here</a> to browse other Qwikis.</p>');
            break;
        case QWIKI.player.data.types.ErrorCodes.DESKTOP_BROWSER_NOT_SUPPORTED:
            QWIKI.logger.error({
                audio:
                Modernizr.audio,
                video: Modernizr.video,
                SVG: Modernizr.svg,
                SVGClipPaths: Modernizr.svgclippaths
            });
            var n = '<h2>A Qwiki Lives Here</h2><h3>Sorry you can\'t play it</h3><p>We\'re working hard on making Qwiki available for all browsers.In the meantime, try the latest version of Chrome, Safari, Firefox or Internet Explorer:</p><a href="http://google.com/chrome"><img title="Chrome" src="//d1gk3e6myre8ic.cloudfront.net/web-player/2.3/images/browser-chrome-64x64.png"></a><a href="http://www.apple.com/safari/download/"><img title="Safari 5.1 and higher" src="//d1gk3e6myre8ic.cloudfront.net/web-player/2.3/images/browser-safari-64x64.png"></a><a href="http://www.mozilla.org/en-US/firefox/"><img title="Firefox 4 and higher" src="//d1gk3e6myre8ic.cloudfront.net/web-player/2.3/images/browser-firefox-64x64.png"></a>';
            BrowserDetect.OS === "Windows" && (n += '<a href="http://www.microsoft.com/ie9"><img title="Internet Explorer 9" src="//d1gk3e6myre8ic.cloudfront.net/web-player/2.3/images/browser-ie9-64x64.png"></a>'),
            QWIKI.player.Player.crash(n);
            break;
        case QWIKI.player.data.types.ErrorCodes.DESKTOP_BROWSER_NO_MEDIA_SUPPORT:
            QWIKI.player.Player.crash("<h2>A Qwiki Lives Here</h2><h3>Sorry you can't play it</h3><p>Unfortunately your browser isn't capable of playing our media.We're working hard on making Qwiki available for all browsers.</p>");
            break;
        case QWIKI.player.data.types.ErrorCodes.MOBILE_BROWSER_NOT_SUPPORTED:
            QWIKI.player.Player.crash("<h2>A Qwiki Lives Here</h2><h3>Sorry you can't play it</h3><p>We're working hard on making Qwiki available for more mobile devices.</p>")
        }
    }
},
QWIKI.ns("player.signal"),
QWIKI.player.signal.Fonts = {
    init: function() {
        var e = {
            custom: {
                families: ["Qwikons"],
                urls: [QWIKI.player.config.Resources.QWIKONS]
            },
            loading: function() {}.bind(this),
            fontloading: function(e, t) {}.bind(this),
            fontactive: function(e, t) {
                e === "Qwikons" && $("html").addClass("icons-active")
            }.bind(this),
            fontinactive: function(e, t) {}.bind(this),
            active: function() {}.bind(this),
            inactive: function() {}.bind(this)
        };
        WebFont.load(e)
    }
},
QWIKI.ns("util"),
QWIKI.util.ObjectUtil = {
    stringify: function(e, t, n) {
        n = n + 1 || 0;
        if (n > t) return "...";
        var r = QWIKI.util.StringUtil.repeat("   ", n),
        i = "";
        for (var s in e) {
            var o = e[s];
            i += i === "" ? "": ", \n";
            switch (typeof o) {
            case "function":
                o = "function(){...}";
                break;
            case "object":
                o = "{ \n" + QWIKI.util.ObjectUtil.stringify(o, t, n) + " \n" + r + "}"
            }
            i += r + s + ": " + (o || "empty")
        }
        return i
    },
    length: function(e) {
        var t = 0;
        for (var n in e) t++;
        return t
    },
    extend: function(e, t, n) {
        for (var r in t) if (!e[r] || n) e[r] = t[r]
    },
    either: function(e, t) {
        return e === undefined || e === null || typeof e == "number" && !!isNaN(e) ? t: e
    },
    clone: function(e) {
        var t = {};
        for (var n in e) t[n] = typeof e[n] == "object" ? QWIKI.util.ObjectUtil.clone(e[n]) : e[n];
        return t
    }
},
QWIKI.ns("util"),
QWIKI.util.StringUtil = {
    EMAIL_EXPRESSION: /^[A-Z0-9._%+\-]+@[A-Z0-9.\-]+\.[A-Z]{2,4}$/gi,
    URL_EXPRESSION: /((http|https|ftp):\/\/(\S*?\.\S*?))(\s|\;|\)|\]|\[|\{|\}|,|\"|'|:|<|$|\.\s)/gi,
    ID_PREFIX: 0,
    repeat: function(e, t) {
        var n = "";
        while (t--) n += e;
        return n
    },
    prefixZeroes: function(e, t) {
        e = e.toString();
        while (e.length < t) e = "0" + e;
        return e
    },
    uniqueId: function(e) {
        return e + QWIKI.util.StringUtil.ID_PREFIX++
    },
    truncate: function(e, t) {
        return e.length < t ? e: e.slice(0, t - 3) + "..."
    },
    decodeHTMLEntities: function(e) {
        return e.replace("&amp", "&")
    },
    hasFileExtension: function(e, t) {
        var n = e.lastIndexOf("." + t);
        return n > 0 && n + (1 + t.length) === e.length
    },
    replaceFileExtension: function(e, t, n) {
        return QWIKI.util.StringUtil.hasFileExtension(e, t) ? e.slice(0, e.lastIndexOf("." + t)) + "." + n: e
    },
    getFileHashFromURL: function(e) {
        return (e || "").replace(/(.*)\//gi, "").replace(/\.(.*)/gi, "")
    },
    isEmail: function(e) {
        return e.match(this.EMAIL_EXPRESSION) !== null
    },
    isURL: function(e) {
        return e && e.match(this.URL_EXPRESSION) !== null
    },
    isImageURL: function(e) {
        return e && e.match(/\.(jpg|jpeg|gif|png)$/gi)
    },
    isPath: function(e) {
        return e.indexOf("/") === 0
    }
},
QWIKI.ns("util"),
QWIKI.util.FunctionUtil = {
    argumentsToArray: function(e) {
        return Array.prototype.slice.call(e)
    }
},
QWIKI.ns("util"),
QWIKI.util.Color = Class.extend({
    init: function(e, t) {
        var n = t !== undefined && isNaN(t) === !1,
        r = typeof e;
        this.r = 0,
        this.g = 0,
        this.b = 0,
        this.a = 1;
        if (r === "object" && e.length) this.r = parseInt(e[0], 10),
        this.g = parseInt(e[1], 10),
        this.b = parseInt(e[2], 10),
        this.a = parseFloat(e[3], 10) || 1;
        else if (r === "string" && e.match("#")) {
            e = e.split("#").join("");
            try {
                this.r = QWIKI.util.ObjectUtil.either(parseInt(e.slice(0, 2), 16), 0),
                this.g = QWIKI.util.ObjectUtil.either(parseInt(e.slice(2, 4), 16), 0),
                this.b = QWIKI.util.ObjectUtil.either(parseInt(e.slice(4, 6), 16), 0),
                n ? this.a = t: this.a = e.length > 6 ? parseInt(e.slice(6, 8), 10) / 255 : 1
            } catch(i) {}
        } else r === "string" && e.match("rgb") ? (e = e.replace(/rgb(a?)\(|\)| /gi, "").split(","), this.r = parseInt(e[0], 10), this.g = parseInt(e[1], 10), this.b = parseInt(e[2], 10), this.a = parseFloat(e[3], 10), this.a = this.a === undefined ? 1 : this.a) : r === "object" && (this.r = e.r || 0, this.g = e.g || 0, this.b = e.b || 0, this.a = n ? t: e.a || 1)
    },
    brightness: function(e) {
        return this.r = Math.min(Math.max(this.r * e, 0), 255),
        this.g = Math.min(Math.max(this.g * e, 0), 255),
        this.b = Math.min(Math.max(this.b * e, 0), 255),
        this.round(),
        this
    },
    saturation: function(e) {
        var t = (this.r + this.g + this.b) / 3;
        return this.r += (t - this.r) * (1 - e),
        this.g += (t - this.g) * (1 - e),
        this.b += (t - this.b) * (1 - e),
        this.round(),
        this
    },
    round: function() {
        return this.r = Math.round(this.r),
        this.g = Math.round(this.g),
        this.b = Math.round(this.b),
        this
    },
    clone: function() {
        return new QWIKI.util.Color(this)
    },
    getRGB: function() {
        return this.round(),
        "rgb(" + this.r + "," + this.g + "," + this.b + ")"
    },
    getRGBA: function(e) {
        return this.round(),
        "rgba(" + this.r + "," + this.g + "," + this.b + "," + (e ? e: this.a) + ")"
    },
    getSupportedRGBA: function(e) {
        return Modernizr && Modernizr.rgba ? this.getRGBA(e) : this.getRGB()
    },
    getHEX: function() {
        return this.round(),
        "#" + QWIKI.util.StringUtil.prefixZeroes(this.r.toString(16), 2) + QWIKI.util.StringUtil.prefixZeroes(this.g.toString(16), 2) + QWIKI.util.StringUtil.prefixZeroes(this.b.toString(16), 2)
    },
    getHEX24: function(e) {
        return this.round(),
        this.getHEX() + QWIKI.util.StringUtil.prefixZeroes(((typeof e != "undefined" ? e: this.a) * 255).toString(16), 2)
    }
}),
QWIKI.util.Color.random = function() {
    return new QWIKI.util.Color({
        r: Math.floor(Math.random() * 255),
        g: Math.floor(Math.random() * 255),
        b: Math.floor(Math.random() * 255)
    })
},
function() {
    var e = ["ms", "moz", "webkit", "o"];
    for (var t = 0; t < e.length && !window.requestAnimationFrame; ++t) window.requestAnimationFrame = window[e[t] + "RequestAnimationFrame"],
    window.cancelAnimationFrame = window[e[t] + "CancelAnimationFrame"] || window[e[t] + "CancelRequestAnimationFrame"];
    window.requestAnimationFrame || (window.requestAnimationFrame = function(e, t) {
        var n = window.setTimeout(function() {
            e()
        },
        16.6);
        return n
    }),
    window.cancelAnimationFrame || (window.cancelAnimationFrame = function(e) {
        clearTimeout(e)
    })
} ();
var State = Class.extend({
    memory: {},
    current: 0,
    changed: null,
    init: function() {
        this.changed = new signals.Signal,
        arguments.length && this.set.apply(this, arguments)
    },
    set: function() {
        var e = this.current;
        for (var t = 0,
        n = arguments.length; t < n; t++) this.current |= arguments[t];
        return this.current !== e && this.changed.dispatch(this),
        this
    },
    unset: function() {
        var e = this.current;
        for (var t = 0,
        n = arguments.length; t < n; t++) this.current &= ~arguments[t];
        return this.current !== e && this.changed.dispatch(this),
        this
    },
    toggle: function(e, t) {
        t ? this.set(e) : this.unset(e)
    },
    is: function() {
        for (var e = 0,
        t = arguments.length; e < t; e++) if (! (this.current & arguments[e])) return ! 1;
        return ! 0
    },
    was: function(e, t) {
        return !! (this.memory[e] & t)
    },
    memorize: function(e) {
        this.memory[e] = this.current
    },
    forget: function(e) {
        this.memory[e] = 0
    },
    reset: function() {
        this.current = 0,
        this.memory = {}
    }
});
State.LOADING = 1,
State.LOADED = 2,
State.PRELOADED = 4,
State.FAILED = 8,
State.VISIBLE = 16,
State.OPENED = 32,
State.ACTIVE = 64,
State.SEEKING = 128,
State.BUFFERING = 256,
State.PLAYING = 512,
State.PAUSED = 1024,
State.ANIMATING = 2048,
State.HOVERED = 4096,
State.BROKEN = 8192,
State.ENDED = 16384,
QWIKI.ns("util"),
QWIKI.util.Queue = Class.extend({
    tasks: null,
    init: function() {
        this.tasks = []
    },
    push: function(e, t, n) {
        if (typeof t != "function") throw "A Queue may only contain functions.";
        e || n ? this.tasks.push(function() {
            t.apply(e, n)
        }) : this.tasks.push(t)
    },
    pop: function(e) {
        e = e || 1;
        while (e--&&this.tasks.length) this.tasks.pop().apply(null)
    },
    shift: function(e) {
        e = e || 1;
        while (e--&&this.tasks.length) this.tasks.shift().apply(null)
    },
    reset: function() {
        this.tasks.length = 0
    },
    isEmpty: function() {
        return this.tasks.length === 0
    }
}),
QWIKI.ns("util"),
QWIKI.util.DOMUtil = {
    align: function(e, t, n) {
        if (!e) throw "Invalid argument, element is not defined";
        var r = "initial",
        i = "initial",
        s = "initial",
        o = "initial";
        e = $(e),
        n = n || e.parent();
        switch (t) {
        case QWIKI.player.data.types.Alignment.T:
            i = (n.width() - e.width()) / 2,
            r = 0;
            break;
        case QWIKI.player.data.types.Alignment.TL:
            i = 0,
            r = 0;
            break;
        case QWIKI.player.data.types.Alignment.TR:
            s = 0,
            r = 0;
            break;
        case QWIKI.player.data.types.Alignment.B:
            i = (n.width() - e.width()) / 2,
            o = 0;
            break;
        case QWIKI.player.data.types.Alignment.BL:
            i = 0,
            o = 0;
            break;
        case QWIKI.player.data.types.Alignment.BR:
            s = 0,
            o = 0;
            break;
        case QWIKI.player.data.types.Alignment.L:
            i = 0,
            r = (n.height() - e.height()) / 2;
            break;
        case QWIKI.player.data.types.Alignment.R:
            s = 0,
            r = (n.height() - e.height()) / 2;
            break;
        case QWIKI.player.data.types.Alignment.C:
            i = (n.width() - e.width()) / 2,
            r = (n.height() - e.height()) / 2
        }
        e.css({
            top: r,
            left: i,
            right: s,
            bottom: o
        })
    },
    fit: function(e, t, n, r, i, s) {
        if (!e) throw "Invalid argument, element is not defined";
        e = $(e);
        var o = 1;
        switch (s) {
        case QWIKI.player.data.types.FitType.INSIDE:
        case QWIKI.player.data.types.FitType.DUPLICATE:
            o = Math.min(r / t, i / n);
            break;
        case QWIKI.player.data.types.FitType.OUTSIDE:
            o = Math.max(r / t, i / n)
        }
        var u = t * o,
        a = n * o;
        e.css({
            width: Math.round(u),
            height: Math.round(a),
            left: (r - u) * .5,
            top: (i - a) * .5
        })
    }
},
QWIKI.ns("util"),
QWIKI.util.Network = {
    speedTest: function(e, t, n) {
        var r = Date.now(),
        i,
        s = $("<img>");
        s.on("load",
        function() {
            i = Date.now();
            var e = (i - r) / 1e3,
            s = t * 8,
            o = (s / e).toFixed(2),
            u = (o / 1024).toFixed(2),
            a = (u / 1024).toFixed(2);
            n.call(null, {
                bps: o,
                kbps: u,
                mbps: a
            })
        }),
        s.error("load",
        function() {
            n.call()
        }),
        s.attr("src", e + "?n=" + Math.random())
    }
},
QWIKI.ns("player.config"),
QWIKI.player.config.Resources = {
    init: function() {
        QWIKI.player.signal.Advisor.isInDevelopment() ? this.FLASH_MEDIA_PLAYER = "/assets/swf/QwikiMediaPlayer.swf": this.FLASH_MEDIA_PLAYER = "//d1gk3e6myre8ic.cloudfront.net/web-player/4.0/QwikiMediaPlayer.swf"
    },
    QWIKONS: "//s3.amazonaws.com/static.qwiki.com/web-player/3.0/fonts/qwikons/qwikons.css",
    EMBED_SCRIPT: "http://s1.ikiwq.com/embed/3.0/embed.min.js",
    APP_ICON: "//d1gk3e6myre8ic.cloudfront.net/web-player/4.0/app-icon-114.png",
    APP_STORE_BADGE: "//d1gk3e6myre8ic.cloudfront.net/web-player/3.0/images/appstore_black_135x40.svg",
    QWIKI_LOGO: "//d1gk3e6myre8ic.cloudfront.net/web-player/3.0/images/splash-qwiki-logo.png",
    SPEED_TEST_FILE: "//d1gk3e6myre8ic.cloudfront.net/web-player/3.0/images/size-test.jpg",
    SPEED_TEST_FILE_SIZE: 32684
},
QWIKI.ns("player.config"),
QWIKI.player.config.Layout = {
    DEFAULT_WIDTH: 640,
    DEFAULT_HEIGHT: 360,
    init: function(e, t) {
        e = e || this.DEFAULT_WIDTH,
        t = t || this.DEFAULT_HEIGHT,
        this.SCALE = Math.min(e / this.DEFAULT_WIDTH, t / this.DEFAULT_HEIGHT),
        this.PLAYER_WIDTH = e,
        this.PLAYER_HEIGHT = t,
        this.PROJECTOR_WIDTH = e,
        this.PROJECTOR_HEIGHT = t,
        QWIKI.player.signal.Advisor.isWebCapableMobile() && (this.PROJECTOR_HEIGHT -= 40),
        this.BACKGROUND_WIDTH = e,
        this.BACKGROUND_HEIGHT = t,
        this.FOOTER_HEIGHT = 40
    }
},
QWIKI.ns("player.config"),
QWIKI.player.config.Player = {
    FRAMERATE: 60,
    OPEN_IN_APP_FLAG: "qwiki-mobile-auto-open-in-app-3",
    VIDEO_TIMEOUT: 12e3
},
QWIKI.ns("io"),
QWIKI.io.Settings = {
    STORAGE_KEY: "qwiki-player-settings",
    STORAGE_VERSION: 2,
    init: function() {
        this.settings = {
            version: this.STORAGE_VERSION,
            volume: 1,
            mute: !1,
            subtitles: !0
        },
        this.changed = new signals.Signal,
        this.restore()
    },
    setValue: function(e, t) {
        typeof e == "object" ? $.extend(this.settings, e) : this.settings[e] = t,
        this.save(),
        this.changed.dispatch([e])
    },
    getValue: function(e) {
        return this.settings[e]
    },
    restore: function() {
        if (Modernizr.localstorage) {
            var e = localStorage.getItem(this.STORAGE_KEY);
            if (e) {
                var t = JSON.parse(localStorage.getItem(this.STORAGE_KEY));
                t && t.version === this.STORAGE_VERSION ? (this.settings = t, this.changed.dispatch()) : this.save()
            }
        }
    },
    save: function() {
        Modernizr.localstorage && localStorage.setItem(this.STORAGE_KEY, JSON.stringify(this.settings))
    }
},
QWIKI.ns("io"),
QWIKI.io.Logger = {
    info: function() {
        this.canLog(4) && window.console.info(arguments.length > 1 ? QWIKI.util.FunctionUtil.argumentsToArray(arguments) : arguments[0])
    },
    log: function() {
        this.canLog(3) && window.console.log(arguments.length > 1 ? QWIKI.util.FunctionUtil.argumentsToArray(arguments) : arguments[0])
    },
    warn: function() {
        this.canLog(2) && window.console.warn(arguments.length > 1 ? QWIKI.util.FunctionUtil.argumentsToArray(arguments) : arguments[0])
    },
    error: function() {
        this.canLog(1) && window.console.error(arguments.length > 1 ? QWIKI.util.FunctionUtil.argumentsToArray(arguments) : arguments[0])
    },
    canLog: function(e) {
        return QWIKI.DEBUG && QWIKI.DEBUG >= e && window.console && window.console.log
    }
},
QWIKI.ns("io"),
QWIKI.io.Query = function() {
    var e = {};
    return location.search.replace(/[A-Z0-9]+?=(\w*)/gi,
    function(t) {
        e[t.split("=").shift()] = t.split("=").pop()
    }),
    {
        getValue: function(t) {
            return e[t]
        }
    }
} (),
QWIKI.ns("player"),
QWIKI.player.Player = function(e) {
    function T(e) {
        N(e) && (t = $.extend({
            embed: !1,
            replay: !1,
            autoplay: !0,
            useflash: !1,
            width: QWIKI.player.config.Layout.DEFAULT_WIDTH,
            height: QWIKI.player.config.Layout.DEFAULT_HEIGHT
        },
        e), typeof e.autoplay == "undefined" && e.embed === !0 && (t.autoplay = !1), s = $(t.element), n = new State, C(), QWIKI.player.config.Resources.init(), QWIKI.player.signal.Fonts.init(), QWIKI.player.signal.Tracking.onInitialized())
    }
    function N(e) {
        if (typeof e == "undefined") throw "Missing player initialization options";
        if (!e.element) throw "Invalid player options (element must be defined)";
        if (typeof e.width != typeof e.height) throw "Player width and height settings must be of same type";
        if (typeof e.width == "string" && e.width !== "100%" && typeof e.height == "string" && e.height !== "100%") throw "Player width and height must be numerical or 100%";
        return ! 0
    }
    function C() {
        s.toggleClass("touch", QWIKI.player.signal.Advisor.isTouchDevice()),
        s.toggleClass("mobile-app", QWIKI.player.signal.Advisor.isAppCapableMobile()),
        s.toggleClass("mobile-web", QWIKI.player.signal.Advisor.isWebCapableMobile()),
        navigator.userAgent.match(/MSIE\s[0-9]/gi) && $("html").addClass("ie" + navigator.userAgent.match(/MSIE\s[0-9]/gi)[0].split("").pop()),
        QWIKI.player.signal.Advisor.isWebCapableMobile() && (QWIKI.player.signal.Advisor.isIOS4() || QWIKI.player.signal.Advisor.isIOS5()) && s.addClass("no-component-transitions")
    }
    function k() {
        a && a.dispose(),
        l && l.dispose(),
        c && c.dispose(),
        h && h.dispose(),
        p && p.dispose(),
        d && d.dispose(),
        v && v.dispose(),
        m && m.dispose()
    }
    function L() {
        a = new QWIKI.player.components.Background,
        f = new QWIKI.player.components.Soundtrack,
        l = new QWIKI.player.components.Preloader,
        c = new QWIKI.player.components.Warning,
        h = new QWIKI.player.components.Footer,
        p = new QWIKI.player.components.Buffer,
        v = new QWIKI.player.components.Embed,
        m = new QWIKI.player.components.Outro,
        a.appendTo(s),
        f.appendTo(s),
        l.appendTo(s),
        c.appendTo(s),
        h.appendTo(s),
        p.appendTo(s),
        v.appendTo(s),
        m.appendTo(s),
        a.show()
    }
    function A() {
        QWIKI.player.signal.Advisor.useFlashMedia() ? d = new QWIKI.player.components.VideoFlash: d = new QWIKI.player.components.Video,
        d.appendTo(s),
        d.ended.add(Q.bind(this)),
        d.error.add(at.bind(this)),
        d.preloaded.add(G.bind(this)),
        d.updated.add(et.bind(this)),
        d.clicked.add(Z.bind(this)),
        d.state.changed.add(Y.bind(this))
    }
    function O() {
        $(e).on("resize", D.bind(this)),
        h.embedClicked.add(rt.bind(this)),
        h.playClicked.add(it.bind(this)),
        h.seekStarted.add(st.bind(this)),
        h.seekUpdated.add(ot.bind(this)),
        h.seekEnded.add(ut.bind(this)),
        l.playClicked.add(tt.bind(this)),
        v.closeClicked.add(nt.bind(this))
    }
    function M() {
        i = null,
        r = null,
        n.reset(),
        o && o.abort(),
        k(),
        L(),
        O(),
        D()
    }
    function _(e) {
        M();
        if (!e) return ! 1;
        o = $.ajax({
            url: e,
            type: "GET",
            context: this,
            dataType: "text"
        }).error(K).complete(J)
    }
    function D() {
        var n = QWIKI.player.signal.Advisor.isFullScreen() || t.width === "100%" && t.height === "100%";
        n ? QWIKI.player.config.Layout.init(e.innerWidth, e.innerHeight) : QWIKI.player.config.Layout.init(t.width, t.height),
        s.css({
            width: QWIKI.player.config.Layout.PLAYER_WIDTH,
            height: QWIKI.player.config.Layout.PLAYER_HEIGHT
        });
        var r = Math.max(QWIKI.player.config.Layout.SCALE, .2);
        QWIKI.player.signal.Advisor.isPortrait() && (r *= 1.3),
        s.css("font-size", r * 100 + "%"),
        d && d.layout(),
        v && v.layout(),
        l && l.layout(),
        a && a.layout()
    }
    function P() {
        n.is(State.PLAYING) || (n.is(State.PAUSED) && QWIKI.player.signal.Tracking.onPlaybackResumed(), n.set(State.PLAYING).unset(State.PAUSED), i !== QWIKI.player.data.types.QwikiView.BODY && F(QWIKI.player.data.types.QwikiView.BODY), d && d.play())
    }
    function H() {
        n.is(State.PLAYING) && (n.set(State.PAUSED).unset(State.PLAYING), QWIKI.player.signal.Tracking.onPlaybackPaused(), d && d.pause())
    }
    function B() {
        QWIKI.player.signal.Tracking.onPlaybackRestarted(),
        j(0),
        P()
    }
    function j(e) {
        d && d.seek(e)
    }
    function F(e) {
        if (i !== e) {
            i = e;
            switch (i) {
            case QWIKI.player.data.types.QwikiView.IDLE:
                f && (QWIKI.player.signal.Advisor.isMobile() && !navigator.userAgent.match(/ipad/gi) ? f.show() : f.hide()),
                l && l.show(),
                p && p.hide(),
                m && m.hide(),
                d && d.hide(),
                h && h.enable();
                break;
            case QWIKI.player.data.types.QwikiView.BODY:
                f && f.show(),
                l && l.hide(),
                m && m.hide(),
                d && d.show(),
                h && h.enable();
                break;
            case QWIKI.player.data.types.QwikiView.OUTRO:
                p && p.hide(),
                h && h.show(),
                h && h.disable()
            }
            s.removeClass(QWIKI.player.data.types.QwikiView.IDLE + "-view " + QWIKI.player.data.types.QwikiView.BODY + "-view " + QWIKI.player.data.types.QwikiView.OUTRO + "-view"),
            s.addClass(i + "-view")
        }
    }
    function I(e) {
        h.changePlaybackState(e)
    }
    function q() {
        n.is(State.LOADED) ? d.state.is(State.PLAYING) ? H() : P() : n.is(State.LOADING) || R()
    }
    function R() {
        c.hide(),
        n.set(State.LOADING),
        F(QWIKI.player.data.types.QwikiView.BODY),
        p.showAfterDelay(300),
        d && d.load(),
        m && m.load()
    }
    function U() {
        var e = r.getVideoByType("mp4"),
        t = r.getVideoByType("m3u8"),
        n = e;
        t && QWIKI.player.signal.Advisor.isIOS() && (n = r.getVideoByType("m3u8"));
        if (n) {
            p.show();
            var i = $('<video class="mobile-video" src="' + n.src + '">').appendTo(s);
            i.get(0).webkitEnterFullscreen ? (i.on("canplay",
            function() {
                p.hide()
            }.bind(this)), i.on("error",
            function() {
                p.hide(),
                c.show("<h2>Not found</h2><p>This Qwiki may still be processing.</p>", "Retry",
                function() {
                    U()
                })
            }.bind(this)), i.on("ended",
            function() {
                p.hide(),
                i.get(0).src = "",
                i.remove()
            }.bind(this)), i.on("durationchange",
            function() {
                i.get(0).play()
            }.bind(this)), i.on("webkitendfullscreen",
            function() {
                p.hide(),
                i.get(0).src = "",
                i.remove()
            }.bind(this)), i.load(), setTimeout(function() {
                i.get(0).webkitEnterFullscreen()
            },
            1)) : R()
        }
    }
    function z() {
        n.memorize("embed"),
        H(),
        v.show()
    }
    function W() {
        v.hide(),
        n.was("embed", State.PLAYING) && P(),
        n.forget("embed")
    }
    function X() {
        var t = QWIKI.player.signal.Advisor.scalePlayerToFit() && !!navigator.userAgent.match(/iphone;|ipod;/gi) && !e.navigator.standalone;
        if (t) {
            var n = 0;
            e.orientation === 0 ? n = 60 * (document.documentElement.clientHeight / 320) : n = 60 * (document.documentElement.clientWidth / 320),
            $(document.body).height(document.documentElement.clientHeight + 60),
            setTimeout(function() {
                e.scrollTo(0, 1),
                D()
            }.bind(this), 0)
        }
    }
    function V() {
        return v.state.is(State.VISIBLE) || c.state.is(State.VISIBLE)
    }
    function J(n) {
        QWIKI.player.signal.Tracking.onDataLoaded();
        var i = JSON.parse(n.responseText);
        r = new QWIKI.player.data.QwikiData(i),
        t.useflash = r.isPending(),
        (QWIKI.player.signal.Advisor.isWebCapableMobile() || !QWIKI.player.signal.Advisor.isIOS()) && A(),
        a && a.populate(r),
        f && f.populate(r),
        l && l.populate(r),
        h && h.populate(r),
        p && p.populate(r),
        d && d.populate(r),
        v && v.populate(r),
        m && m.populate(r),
        QWIKI.player.signal.Advisor.userInteractionRequiredToPlay() && a.load(),
        g.dispatch();
        if (r.status === "draft") {
            var s = '<h2>THIS QWIKI WILL BE READY SOON</h2><p>It may still be uploading. Contact <a href="mailto:creators@qwiki.com">creators@qwiki.com</a> if this message displays longer than a few minutes</p>';
            c.show(s, "Retry",
            function() {
                e.location.reload()
            })
        }
        QWIKI.player.signal.Advisor.userInteractionRequiredToPlay() ? (F(QWIKI.player.data.types.QwikiView.IDLE), QWIKI.player.signal.Advisor.isIOS() && Modernizr.localstorage && e.localStorage.getItem(QWIKI.player.config.Player.OPEN_IN_APP_FLAG) && (document.location = r.getAppURL()), QWIKI.player.signal.Advisor.isMobile() && !QWIKI.player.signal.Advisor.isWebCapableMobile() && setTimeout(function() {
            D()
        }.bind(this), 1)) : r.status !== "draft" && R()
    }
    function K() {
        QWIKI.player.signal.Tracking.onDataFailed(),
        b.dispatch()
    }
    function Q() {
        h.isSeeking() || (QWIKI.player.signal.Tracking.onPlaybackEnded(), n.unset(State.PLAYING), t.replay ? B() : F(QWIKI.player.data.types.QwikiView.OUTRO))
    }
    function G() {
        n.unset(State.LOADING).set(State.LOADED),
        F(QWIKI.player.data.types.QwikiView.BODY),
        QWIKI.player.signal.Tracking.onPlaybackStarted(),
        P(),
        D(),
        y.dispatch()
    }
    function Y(e) {
        e.is(State.BUFFERING) ? p.showAfterDelay(300) : p.hide(),
        h.setPlaying(e.is(State.PLAYING))
    }
    function Z() {
        q()
    }
    function et() {
        var e = d.metadata.playbackProgress;
        for (var t = 1; t >= 0; t -= .25) e >= t && u < t && (u = e, QWIKI.player.signal.Tracking.onPlaybackProgress(t));
        h.update(d)
    }
    function tt() { ! n.is(State.LOADED) && !n.is(State.LOADING) && (QWIKI.player.signal.Advisor.isMobile() && !QWIKI.player.signal.Advisor.isWebCapableMobile() ? U() : R())
    }
    function nt() {
        W()
    }
    function rt() {
        z()
    }
    function it() {
        q()
    }
    function st(e) {
        n.is(State.LOADED) && (i !== QWIKI.player.data.types.QwikiView.BODY && F(QWIKI.player.data.types.QwikiView.BODY), n.memorize("seek"), d.pause(), d.seek(e * d.metadata.duration))
    }
    function ot(e) {
        n.is(State.LOADED) && d.seek(e * d.metadata.duration)
    }
    function ut() {
        n.is(State.LOADED) && (n.was("seek", State.PLAYING) && (n.set(State.PLAYING).unset(State.PAUSED), d.play()), n.forget("seek"))
    }
    function at() {
        p.hide(),
        h.hide(),
        c.show("<h2>Not found</h2><p>This Qwiki may still be processing.</p>", "Retry",
        function() {
            R()
        }),
        b.dispatch()
    }
    var t, n, r, i, s, o, u = 0,
    a, f, l, c, h, p, d, v, m, g = new signals.Signal,
    y = new signals.Signal,
    b = new signals.Signal,
    w = new signals.Signal,
    E = new signals.Signal,
    S = new signals.Signal,
    x = new signals.Signal;
    return {
        init: T,
        load: _,
        play: P,
        seek: j,
        pause: H,
        replay: B,
        layout: D,
        isOverlaid: V,
        showEmbed: z,
        prepared: g,
        loaded: y,
        error: b,
        started: w,
        ended: E,
        paused: S,
        resumed: x,
        getConfig: function() {
            return t
        },
        getDOMElement: function() {
            return s
        },
        getData: function() {
            return r
        }
    }
} (window),
QWIKI.ns("player.data"),
QWIKI.player.data.QwikiData = Class.extend({
    HOST_MAP: {
        "http://s1.ikiwq.com": "//d1gk3e6myre8ic.cloudfront.net",
        "http://qp1.ikiwq.com": "//d124swhenejuz9.cloudfront.net",
        "http://vp1.ikiwq.com": "//d2japcd9yzs5kz.cloudfront.net",
        "http://staging.qp1.ikiwq.com": "//d1h2xis1c7zbpr.cloudfront.net",
        "http://staging.vp1.ikiwq.com": "//d1qc8tn3s0dvhw.cloudfront.net"
    },
    init: function(e) {
        this.json = e,
        this.updateHosts(this.json),
        this.status = this.json.status,
        this.title = this.json.title,
        this.token = this.json.token,
        this.qwiki_id = this.json.id,
        this.user = this.json.user,
        this.thumbnails = this.json.thumbnails,
        this.video = this.json.video,
        this.background_image = this.json.bg_image_src,
        this.soundtrack_artist = "",
        this.soundtrack_track = "",
        this.parseSoundtrack(),
        this.parseVideo()
    },
    updateHosts: function(e) {
        for (var t in e) if (typeof e[t] == "string") for (var n in this.HOST_MAP) e[t] = e[t].replace(n, this.HOST_MAP[n]);
        else typeof e[t] == "object" && this.updateHosts(e[t])
    },
    parseSoundtrack: function() {
        var e = this.json.soundtrack;
        this.json.soundtrack && this.json.soundtrack && (this.soundtrack_artist = this.json.soundtrack.artistName, this.soundtrack_track = this.json.soundtrack.trackName)
    },
    parseVideo: function() {
        this.isPending() && this.video && this.video.input && (this.video.outputs = [this.video.input])
    },
    isPending: function() {
        return this.status === "pending"
    },
    hasUser: function() {
        return !! this.user && !!this.user.name
    },
    hasSoundtrack: function() {
        return !! this.soundtrack_artist && !!this.soundtrack_track
    },
    hasBackgroundImage: function() {
        return !! this.background_image
    },
    getVideoByType: function(e) {
        if (this.video && this.video.outputs) {
            var t = [];
            for (var n = 0,
            r = this.video.outputs.length; n < r; n++)(new RegExp(this.video.outputs[n].type, "gi")).test(e) && t.push(this.video.outputs[n]);
            if (t.length > 0) return t.sort(function(e, t) {
                return e.width * e.height < t.width * t.height ? 1 : -1
            }),
            t[0]
        }
        return ""
    },
    getWatchURL: function() {
        return "http://www.qwiki.com/v/" + this.token
    },
    getEmbedURL: function() {
        return "http://cdn1.qwiki.com/e/" + this.token
    },
    getAppURL: function() {
        return "qwiki://qwiki?id=" + this.qwiki_id
    }
}),
QWIKI.ns("player.data.types"),
QWIKI.player.data.types.ErrorCodes = {
    WARNINGS: 400,
    ERRORS: 500,
    QWIKI_NOT_FOUND: 501,
    DESKTOP_BROWSER_NOT_SUPPORTED: 502,
    DESKTOP_BROWSER_NO_MEDIA_SUPPORT: 507,
    MOBILE_BROWSER_NOT_SUPPORTED: 503,
    ASSET_FAILED: 504,
    ASSET_TIMEOUT: 505,
    ELEMENT_FAILED: 506
},
QWIKI.ns("player.data.types"),
QWIKI.player.data.types.QwikiView = {
    IDLE: "idle",
    BODY: "body",
    OUTRO: "outro"
},
QWIKI.ns("player.data.types"),
QWIKI.player.data.types.FitType = {
    NONE: "none",
    INSIDE: "inside",
    OUTSIDE: "outside",
    DUPLICATE: "duplicate"
},
QWIKI.ns("player.data.types"),
QWIKI.player.data.types.PlaybackState = {
    PLAYING: 1,
    STOPPED: 2,
    PAUSED: 3,
    SEEKING: 4
},
QWIKI.ns("player.data.types"),
QWIKI.player.data.types.Alignment = {
    T: "top",
    TL: "topleft",
    TR: "topright",
    B: "bottom",
    BL: "bottomleft",
    BR: "bottomright",
    L: "left",
    R: "right",
    C: "center"
},
QWIKI.ns("player.components"),
QWIKI.player.components.Component = Class.extend({
    init: function() {
        this.state = new State,
        this.createDOMElement(),
        this.createSignals()
    },
    createDOMElement: function() {
        this.domElement = $('<div class="component">')
    },
    createSignals: function() {},
    populate: function(e) {
        this.data = e
    },
    show: function() {
        this.state.set(State.VISIBLE),
        this.domElement.addClass("visible")
    },
    hide: function() {
        this.state.unset(State.VISIBLE),
        this.domElement.removeClass("visible")
    },
    appendTo: function(e) {
        this.domElement.appendTo(e)
    },
    dispose: function() {
        this.domElement.remove()
    }
}),
QWIKI.ns("player.components"),
QWIKI.player.components.Background = QWIKI.player.components.Component.extend({
    init: function() {
        this._super()
    },
    createDOMElement: function() {
        this._super(),
        this.domElement.addClass("background")
    },
    load: function() { ! this.state.is(State.LOADING) && !this.state.is(State.LOADED) && this.data.hasBackgroundImage() && (this.state.set(State.LOADING), this.backgroundElement = $("<img>"), this.backgroundElement.on("load", this.onBackgroundImageLoaded.bind(this)), this.backgroundElement.on("error", this.onBackgroundImageFailed.bind(this)), this.backgroundElement.attr("src", this.data.background_image))
    },
    layout: function() {
        this.backgroundElement && QWIKI.util.DOMUtil.fit(this.backgroundElement, this.backgroundElement.get(0).naturalWidth || this.backgroundElement.get(0).width, this.backgroundElement.get(0).naturalHeight || this.backgroundElement.get(0).height, QWIKI.player.config.Layout.BACKGROUND_WIDTH, QWIKI.player.config.Layout.BACKGROUND_HEIGHT, QWIKI.player.data.types.FitType.OUTSIDE)
    },
    onBackgroundImageLoaded: function(e) {
        this.state.unset(State.LOADING).set(State.PRELOADED),
        this.backgroundElement.appendTo(this.domElement),
        this.layout(),
        setTimeout(function() {
            this.domElement.addClass("ready")
        }.bind(this), 1)
    },
    onBackgroundImageFailed: function(e) {
        this.state.unset(State.LOADING).set(State.FAILED)
    },
    dispose: function() {
        this.backgroundElement && this.backgroundElement.attr("src", ""),
        this._super()
    }
}),
QWIKI.ns("player.components"),
QWIKI.player.components.Soundtrack = QWIKI.player.components.Component.extend({
    init: function() {
        this._super()
    },
    createDOMElement: function() {
        this._super(),
        this.domElement.addClass("soundtrack vcenter")
    },
    populate: function(e) {
        this._super(e),
        this.data.hasSoundtrack() && $.ajax({
            type: "GET",
            dataType: "jsonp",
            data: "media=music&term=" + encodeURI(this.data.soundtrack_artist + " " + this.data.soundtrack_track),
            url: "//itunes.apple.com/search",
            context: this,
            success: function(e) {
                var t = "http://www.apple.com/itunes/";
                typeof e != "undefined" && typeof e.results && e.results.length && (t = e.results[0].trackViewUrl),
                $("<a>").addClass("soundtrack-link").attr({
                    href: t,
                    target: "_blank"
                }).text(this.data.soundtrack_artist + " - " + this.data.soundtrack_track).on("click",
                function() {
                    QWIKI.player.Player.pause(),
                    QWIKI.player.signal.Tracking.onSoundtrackClicked()
                }).appendTo(this.domElement)
            }
        })
    },
    show: function() {
        this.data && this.data.hasSoundtrack() && (QWIKI.player.signal.Advisor.isEmbedded() || QWIKI.player.signal.Advisor.isMobile()) && this._super()
    },
    hide: function() {
        this._super()
    },
    dispose: function() {
        this._super()
    }
}),
QWIKI.ns("player.components"),
QWIKI.player.components.Preloader = QWIKI.player.components.Component.extend({
    init: function() {
        this._super(),
        this.addEventListeners()
    },
    createDOMElement: function() {
        this._super(),
        this.domElement.addClass("preloader vcenter"),
        this.innerElement = $('<div class="inner vcenter-target">').appendTo(this.domElement),
        this.actionElement = $('<div class="action">').appendTo(this.innerElement),
        this.playElement = $('<div class="play-button">').appendTo(this.actionElement),
        this.loaderElement = $('<div class="loader">').appendTo(this.actionElement),
        this.titleElement = $("<h1>").appendTo(this.innerElement),
        this.authorElement = $("<h2>").appendTo(this.innerElement);
        if (QWIKI.player.signal.Advisor.useAppBanner()) {
            var e = QWIKI.player.Player.getConfig().appid;
            QWIKI.player.Player.getDOMElement().addClass("has-app-banner"),
            this.domElement.addClass("has-app-banner"),
            this.bannerElement = $('<div class="app-banner">').prependTo(this.domElement),
            typeof e == "string" ? this.iconElement = $('<a class="icon" href="https://itunes.apple.com/us/app/qwiki/id' + e + '?mt=8">').appendTo(this.bannerElement) : this.iconElement = $('<div class="icon">').appendTo(this.bannerElement),
            this.iconElement.append('<img src="' + QWIKI.player.config.Resources.APP_ICON + '" width="57" height="57">'),
            this.attributionElement = $("<p>Created with <b>Qwiki</b> for iPhone</p>").appendTo(this.bannerElement),
            this.playInAppButton = $('<a class="button play-in-app" href="#">Play in App</a>').appendTo(this.bannerElement),
            typeof e == "string" && (this.getTheAppButton = $('<a class="button get-the-app" href="https://itunes.apple.com/us/app/qwiki/id' + e + '?mt=8">Download App</a>').appendTo(this.bannerElement))
        }
        QWIKI.player.signal.Advisor.isMobile() && !QWIKI.player.signal.Advisor.isIOS() && this.domElement.append('<a class="qwiki-logo" href="http://qwiki.com">Created with <img src="' + QWIKI.player.config.Resources.QWIKI_LOGO + '" width="101"></a>')
    },
    createSignals: function() {
        this.playClicked = new signals.Signal
    },
    addEventListeners: function() {
        this.innerElement.on("click", this.onPlayClicked.bind(this))
    },
    layout: function() {
        this.domElement.toggleClass("small", QWIKI.player.config.Layout.SCALE < .8),
        this.domElement.toggleClass("large", QWIKI.player.config.Layout.SCALE > 1.4)
    },
    populate: function(e) {
        this._super(e);
        var t = this.data.title;
        t.length > 45 && (this.titleElement.attr("title", t), t = QWIKI.util.StringUtil.truncate(t, 45)),
        this.titleElement.text(t),
        this.data.hasUser() && this.authorElement.text(this.data.user.username),
        this.playInAppButton && this.playInAppButton.attr("href", this.data.getAppURL())
    },
    show: function() {
        this._super(),
        this.innerElement.removeClass("hidden").addClass("visible")
    },
    hide: function() {
        this._super(),
        this.innerElement.removeClass("visible").addClass("hidden")
    },
    onPlayClicked: function(e) {
        this.playClicked.dispatch()
    },
    onPlayInAppClicked: function(e) {
        if (Modernizr.localstorage) try {
            localStorage.setItem(QWIKI.player.config.Player.OPEN_IN_APP_FLAG, 1)
        } catch(t) {}
    },
    dispose: function() {
        this.playClicked.dispose(),
        this._super()
    }
}),
QWIKI.ns("player.components"),
QWIKI.player.components.Warning = QWIKI.player.components.Component.extend({
    init: function() {
        this._super(),
        this.addEventListeners()
    },
    createDOMElement: function() {
        this._super(),
        this.domElement.addClass("warning vcenter"),
        this.innerElement = $('<div class="inner vcenter-target">').appendTo(this.domElement),
        this.warningElement = $('<div class="message">').appendTo(this.innerElement),
        this.actionElement = $('<button class="action">').appendTo(this.innerElement)
    },
    addEventListeners: function() {
        this.actionElement.on("click", this.onActionClicked.bind(this))
    },
    show: function(e, t, n) {
        if (typeof e != "string" || typeof t != "string" || typeof n != "function") throw "Invalid arguments in Warning#show()";
        this.callback = n,
        this.warningElement.html(e),
        this.actionElement.html(t),
        this._super()
    },
    onActionClicked: function(e) {
        this.callback.apply()
    },
    dispose: function() {
        this._super()
    }
}),
QWIKI.ns("player.components"),
QWIKI.player.components.Buffer = QWIKI.player.components.Component.extend({
    init: function() {
        this._super(),
        this.showTimeout = -1
    },
    createDOMElement: function() {
        this._super(),
        this.domElement.addClass("buffer vcenter"),
        this.innerElement = $('<div class="inner">').appendTo(this.domElement),
        this.spinnerElement = $('<div class="spinner">').appendTo(this.innerElement),
        this.messageElement = $("<p>").text("Loading...").appendTo(this.innerElement)
    },
    show: function() {
        clearTimeout(this.showTimeout),
        this._super()
    },
    showAfterDelay: function(e) {
        clearTimeout(this.showTimeout),
        this.showTimeout = setTimeout(function() {
            this.show()
        }.bind(this), e)
    },
    hide: function() {
        clearTimeout(this.showTimeout),
        this._super()
    },
    dispose: function() {
        clearTimeout(this.showTimeout),
        this._super()
    }
}),
QWIKI.ns("player.components"),
QWIKI.player.components.Footer = QWIKI.player.components.Component.extend({
    SCRUBBER_WIDTH: 24,
    init: function() {
        this.onMouseEnterPlayer = this.onMouseEnterPlayer.bind(this),
        this.onMouseLeavePlayer = this.onMouseLeavePlayer.bind(this),
        this.onFullScreenChange = this.onFullScreenChange.bind(this),
        this.onDocumentMouseMove = this.onDocumentMouseMove.bind(this),
        this.onDocumentKeyDown = this.onDocumentKeyDown.bind(this),
        this.onSettingsChanged = this.onSettingsChanged.bind(this),
        this.onSeekMove = this.onSeekMove.bind(this),
        this.onSeekEnd = this.onSeekEnd.bind(this),
        this.onSeekMoveTouch = this.onSeekMoveTouch.bind(this),
        this.onSeekEndTouch = this.onSeekEndTouch.bind(this),
        this.hideTimeout = -1,
        this.stillTimeout = -1,
        this.enabled = !0,
        this.mouse = {
            x: 0,
            y: 0,
            inside: !1,
            moving: !0,
            lastMove: 0
        },
        this._super(),
        this.addEventListeners(),
        this.setMuted(QWIKI.io.Settings.getValue("mute"))
    },
    createDOMElement: function() {
        this._super(),
        this.domElement.addClass("footer"),
        this.innerElement = $('<div class="inner">').appendTo(this.domElement),
        this.playButton = $("<button></button>").addClass("play").appendTo(this.innerElement),
        this.playButton.append('<span class="text-icon play-icon">p</span><span class="text-icon pause-icon">P</span><span class="text-icon replay-icon">r</span>'),
        this.timerElement = $("<p>").addClass("timer").appendTo(this.innerElement),
        this.timerCurrentElement = $("<span>").addClass("current").appendTo(this.timerElement),
        this.timerDividerElement = $("<span>/</span>").addClass("divider").appendTo(this.timerElement),
        this.timerDurationElement = $("<span>").addClass("duration").appendTo(this.timerElement),
        QWIKI.player.signal.Advisor.supportsFullScreen() && (this.fullscreenButton = $('<button><span class="text-icon">w</span></button>').addClass("fullscreen").appendTo(this.innerElement)),
        this.muteButton = $('<button><span class="text-icon"></span></button>').addClass("mute").appendTo(this.innerElement),
        this.embedButton = $('<button><span class="text-icon">E</span></button>').addClass("embed").appendTo(this.innerElement),
        QWIKI.player.signal.Advisor.displayFooterLogo() && (this.logoButton = $('<button class="logo">').appendTo(this.innerElement), this.logoButton.append('<img src="' + QWIKI.player.config.Resources.QWIKI_LOGO + '" height="18">')),
        this.barElement = $('<div class="progress">').appendTo(this.domElement),
        this.bufferProgressBar = $('<div class="buffer-bar">').appendTo(this.barElement),
        this.playbackProgressBar = $('<div class="playback-bar">').appendTo(this.barElement),
        this.scrubberElement = $('<div class="scrubber">').appendTo(this.barElement)
    },
    createSignals: function() {
        this.embedClicked = new signals.Signal,
        this.playClicked = new signals.Signal,
        this.seekStarted = new signals.Signal,
        this.seekUpdated = new signals.Signal,
        this.seekEnded = new signals.Signal
    },
    addEventListeners: function() {
        QWIKI.io.Settings.changed.add(this.onSettingsChanged),
        this.playButton.on("touchstart click", this.onPlayClicked.bind(this)),
        this.muteButton.on("click", this.onMuteClicked.bind(this)),
        this.embedButton.on("click", this.onEmbedClicked.bind(this)),
        this.fullscreenButton && this.fullscreenButton.on("click", this.onFullscreenClicked.bind(this)),
        this.logoButton && this.logoButton.on("touchstart click", this.onLogoClicked.bind(this)),
        QWIKI.player.signal.Advisor.isTouchDevice() ? this.barElement.get(0).addEventListener("touchstart", this.onSeekStartTouch.bind(this), !1) : this.barElement.on("mousedown", this.onSeekStart.bind(this)),
        $(document).on("webkitfullscreenchange", this.onFullScreenChange),
        $(document).on("mozfullscreenchange", this.onFullScreenChange),
        $(document).on("fullscreenchange", this.onFullScreenChange),
        $(document).on("mousemove", this.onDocumentMouseMove),
        $(document).on("keydown", this.onDocumentKeyDown),
        QWIKI.player.Player.getDOMElement().on("mouseenter", this.onMouseEnterPlayer),
        QWIKI.player.Player.getDOMElement().on("mouseleave", this.onMouseLeavePlayer)
    },
    show: function() {
        if (!QWIKI.player.signal.Advisor.isMobile() || QWIKI.player.signal.Advisor.isWebCapableMobile()) this._super(),
        clearTimeout(this.hideTimeout)
    },
    hide: function() {
        QWIKI.player.signal.Advisor.isTouchDevice() || (this._super(), clearTimeout(this.hideTimeout))
    },
    enable: function() {
        this.enabled = !0
    },
    disable: function() {
        this.enabled = !1
    },
    hideAfterDelay: function(e) {
        if (!this.mouse.inside || !this.mouse.moving) clearTimeout(this.hideTimeout),
        this.hideTimeout = setTimeout(function() {
            this.hide()
        }.bind(this), e)
    },
    setMuted: function(e) {
        this.muteButton.toggleClass("on", e),
        this.muteButton.find(".text-icon").text(e ? "M": "m")
    },
    changeView: function(e) {
        e === QWIKI.player.data.types.QwikiView.BODY ? this.domElement.addClass("active") : this.domElement.removeClass("active")
    },
    setPlaying: function(e) {
        this.playButton.removeClass("state-playing state-paused"),
        e ? this.playButton.addClass("state-playing") : this.playButton.addClass("state-paused")
    },
    update: function(e) {
        this.timerElement.addClass("visible"),
        this.bufferProgressBar.css("width", e.metadata.bufferProgress * 100 + "%"),
        this.state.is(State.SEEKING) || this.setPlaybackProgress(e.metadata.playbackProgress);
        var t = e.metadata.playbackProgress * e.metadata.duration,
        n = Math.floor(t / 60),
        r = Math.floor(t - n * 60),
        i = Math.floor(e.metadata.duration / 60),
        s = Math.floor(e.metadata.duration - i * 60);
        this.timerCurrentElement.text(n + ":" + QWIKI.util.StringUtil.prefixZeroes(r, 2)),
        this.timerDurationElement.text(i + ":" + QWIKI.util.StringUtil.prefixZeroes(s, 2))
    },
    setPlaybackProgress: function(e) {
        var t = e * this.barElement.width();
        t -= this.SCRUBBER_WIDTH / 2,
        t = Math.max(Math.min(t, this.barElement.width() - this.SCRUBBER_WIDTH - 3), -3),
        this.playbackProgressBar.css("width", e * 100 + "%"),
        this.scrubberElement.css("left", t)
    },
    isSeeking: function() {
        return this.state.is(State.SEEKING)
    },
    onMouseEnterPlayer: function() {
        this.mouse.inside = !0,
        QWIKI.player.Player.isOverlaid() || this.show()
    },
    onMouseLeavePlayer: function() { ! this.state.is(State.SEEKING) && this.enabled && (this.mouse.inside = !1, this.hideAfterDelay(400))
    },
    onSettingsChanged: function(e) {
        this.setMuted(QWIKI.io.Settings.getValue("mute"))
    },
    onPlayClicked: function(e) {
        e && e.preventDefault(),
        this.playClicked.dispatch()
    },
    onMuteClicked: function(e) {
        QWIKI.player.signal.Tracking.onMuteClicked(!QWIKI.io.Settings.getValue("mute")),
        QWIKI.io.Settings.setValue("mute", !QWIKI.io.Settings.getValue("mute"))
    },
    onEmbedClicked: function(e) {
        QWIKI.player.signal.Tracking.onEmbedClicked(),
        this.embedClicked.dispatch()
    },
    onFullscreenClicked: function(e) {
        if (QWIKI.player.signal.Advisor.isFullScreen()) QWIKI.player.signal.Tracking.onFullScreenClicked(!1),
        document.webkitCancelFullScreen ? document.webkitCancelFullScreen() : document.mozCancelFullScreen ? document.mozCancelFullScreen() : document.cancelFullScreen && document.cancelFullScreen();
        else {
            QWIKI.player.signal.Tracking.onFullScreenClicked(!0);
            var t = QWIKI.player.Player.getDOMElement().get(0);
            t.webkitRequestFullScreen ? t.webkitRequestFullScreen() : t.mozRequestFullScreen ? t.mozRequestFullScreen() : t.requestFullScreen && t.requestFullScreen()
        }
    },
    onLogoClicked: function(e) {
        e.preventDefault(),
        QWIKI.player.Player.pause(),
        QWIKI.player.signal.Tracking.onFooterLogoClicked(),
        window.open(this.data.getWatchURL())
    },
    onFullScreenChange: function(e) {
        this.fullscreenButton.find(".text-icon").text(QWIKI.player.signal.Advisor.isFullScreen() ? "W": "w"),
        QWIKI.player.Player.layout()
    },
    onDocumentKeyDown: function(e) {
        e.keyCode === 32 && !e.target.nodeName.match(/textarea|input/gi) && (e.preventDefault(), this.onPlayClicked())
    },
    onSeekStart: function(e) {
        e.preventDefault(),
        this.state.set(State.SEEKING),
        $(document).on("mousemove", this.onSeekMove),
        $(document).on("mouseup", this.onSeekEnd),
        this.barElement.addClass("seeking");
        var t = Math.min(Math.max((e.clientX - this.barElement.offset().left - 4) / this.barElement.width(), 0), 1);
        this.seekStarted.dispatch(t),
        this.setPlaybackProgress(t)
    },
    onSeekMove: function(e) {
        e.preventDefault();
        var t = Math.min(Math.max((e.clientX - this.barElement.offset().left - 4) / this.barElement.width(), 0), 1);
        this.seekStarted.dispatch(t),
        this.setPlaybackProgress(t)
    },
    onSeekEnd: function(e) {
        e.preventDefault(),
        QWIKI.player.signal.Tracking.onSeeked(),
        this.state.unset(State.SEEKING),
        $(document).off("mousemove", this.onSeekMove),
        $(document).off("mouseup", this.onSeekEnd),
        this.barElement.removeClass("seeking"),
        this.seekEnded.dispatch(),
        this.mouse.inside || this.onMouseLeavePlayer()
    },
    onSeekStartTouch: function(e) {
        e.preventDefault();
        if (e.touches && e.touches.length === 1) {
            this.state.set(State.SEEKING);
            var t = Math.min(Math.max((e.touches[0].clientX - this.barElement.offset().left) / this.barElement.width(), 0), 1);
            this.seekStarted.dispatch(t),
            this.setPlaybackProgress(t),
            document.addEventListener("touchmove", this.onSeekMoveTouch, !1),
            document.addEventListener("touchend", this.onSeekEndTouch, !1),
            this.barElement.addClass("seeking")
        }
    },
    onSeekMoveTouch: function(e) {
        e.preventDefault();
        var t = Math.min(Math.max((e.touches[0].clientX - this.barElement.offset().left) / this.barElement.width(), 0), 1);
        this.seekUpdated.dispatch(t),
        this.setPlaybackProgress(t)
    },
    onSeekEndTouch: function(e) {
        e.preventDefault(),
        QWIKI.player.signal.Tracking.onSeeked(),
        this.state.unset(State.SEEKING),
        document.removeEventListener("touchmove", this.onSeekMoveTouch, !1),
        document.removeEventListener("touchend", this.onSeekEndTouch, !1),
        this.barElement.removeClass("seeking"),
        this.seekEnded.dispatch(),
        this.mouse.inside || this.onMouseLeavePlayer()
    },
    onDocumentMouseMove: function(e) {
        clearInterval(this.stillTimeout);
        var t = this.enabled && this.mouse.inside && (this.mouse.x !== e.clientX || this.mouse.y !== e.clientY) && !QWIKI.player.Player.isOverlaid();
        t && (QWIKI.player.Player.getDOMElement().removeClass("no-cursor"), this.mouse.moving = !0, this.show(), e.clientY < QWIKI.player.config.Layout.PLAYER_HEIGHT - QWIKI.player.config.Layout.FOOTER_HEIGHT - 10 && (this.stillTimeout = setTimeout(function() {
            QWIKI.player.Player.getDOMElement().addClass("no-cursor"),
            this.mouse.moving = !1,
            this.hide()
        }.bind(this), 2200))),
        this.mouse.x = e.clientX,
        this.mouse.y = e.clientY
    },
    dispose: function() {
        this.embedClicked.dispose(),
        this.playClicked.dispose(),
        this.seekStarted.dispose(),
        this.seekUpdated.dispose(),
        this.seekEnded.dispose(),
        clearTimeout(this.hideTimeout),
        clearTimeout(this.stillTimeout),
        document.removeEventListener("webkitfullscreenchange", this.onFullScreenChange),
        document.removeEventListener("mozfullscreenchange", this.onFullScreenChange),
        document.removeEventListener("fullscreenchange", this.onFullScreenChange),
        QWIKI.player.Player.getDOMElement().off("mouseenter", this.onMouseEnterPlayer),
        QWIKI.player.Player.getDOMElement().off("mouseleave", this.onMouseLeavePlayer),
        QWIKI.io.Settings.changed.remove(this.onSettingsChanged),
        this._super()
    }
}),
QWIKI.ns("player.components"),
QWIKI.player.components.Outro = QWIKI.player.components.Component.extend({
    init: function() {
        this._super(),
        this.addEventListeners()
    },
    createDOMElement: function() {
        this._super(),
        this.domElement.addClass("outro vcenter"),
        this.backgroundWrapperElement = $('<div class="background">').appendTo(this.domElement),
        this.innerElement = $('<div class="inner vcenter-target">').appendTo(this.domElement),
        this.replayButton = $('<button class="replay">Replay</button>').appendTo(this.innerElement),
        this.replayButton.prepend('<span class="text-icon">r</span>'),
        this.innerElement.append("<p><strong>Created with Qwiki.</strong></p>"),
        this.innerElement.append('<p class="fragment-1">See what Qwiki creates for you.</p>');
        var e = QWIKI.player.Player.getConfig().appid;
        typeof e == "string" ? (this.innerElement.append('<p class="fragment-2">Download our free app for iPhone.</p>'), this.innerElement.append($('<a class="fragment-3 app-store-badge" href="https://itunes.apple.com/us/app/qwiki/id' + e + '?mt=8" target="_blank">').append('<img src="' + QWIKI.player.config.Resources.APP_STORE_BADGE + '">'))) : this.innerElement.append('<p class="fragment-2">Coming soon to the iPhone.</p>')
    },
    load: function() { ! this.state.is(State.LOADING) && !this.state.is(State.LOADED) && this.data.hasBackgroundImage() && (this.state.set(State.LOADING), this.backgroundElement = $("<img>"), this.backgroundElement.on("load", this.onBackgroundImageLoaded.bind(this)), this.backgroundElement.on("error", this.onBackgroundImageFailed.bind(this)), this.backgroundElement.attr("src", this.data.background_image))
    },
    layout: function() {
        this.backgroundElement && QWIKI.util.DOMUtil.fit(this.backgroundElement, this.backgroundElement.get(0).naturalWidth || this.backgroundElement.get(0).width, this.backgroundElement.get(0).naturalHeight || this.backgroundElement.get(0).height, QWIKI.player.config.Layout.BACKGROUND_WIDTH, QWIKI.player.config.Layout.BACKGROUND_HEIGHT, QWIKI.player.data.types.FitType.OUTSIDE)
    },
    show: function() {
        this._super()
    },
    addEventListeners: function() {
        this.replayButton.on("click", this.onReplayClick.bind(this))
    },
    onReplayClick: function(e) {
        QWIKI.player.Player.replay()
    },
    onBackgroundImageLoaded: function(e) {
        this.state.unset(State.LOADING).set(State.PRELOADED),
        this.backgroundElement.appendTo(this.backgroundWrapperElement),
        this.layout(),
        setTimeout(function() {
            this.domElement.addClass("ready")
        }.bind(this), 1)
    },
    onBackgroundImageFailed: function(e) {
        this.state.unset(State.LOADING).set(State.FAILED)
    },
    dispose: function() {
        this._super()
    }
}),
QWIKI.ns("player.components"),
QWIKI.player.components.Embed = QWIKI.player.components.Component.extend({
    EMBED_SMALL: [490, 276],
    EMBED_MEDIUM: [640, 360],
    EMBED_LARGE: [960, 540],
    MINIMUM_SIZE: [360, 203],
    EMBED_AR: 16 / 9,
    selectedTab: "",
    init: function() {
        this._super(),
        this.addEventListeners()
    },
    createDOMElement: function() {
        this._super(),
        this.domElement.addClass("embed vcenter");
        var e = ['<div class="inner vcenter-target">', "<header>", "<h3>Embed</h3>", '<a href="#" class="close-button"><span class="text-icon">X</span>Close</a>', "</header>", '<div class="body">', '<div class="social">', "</div>", '<div class="embed">', '<div class="radio-group">', '<label for="embed-small">Small <input type="radio" name="size" id="embed-small" value="small"></label>', '<label for="embed-medium" class="selected">Medium <input type="radio" name="size" id="embed-medium" value="medium" checked></label>', '<label for="embed-large">Large <input type="radio" name="size" id="embed-large" value="large"></label>', "</div>", '<div class="size-input">', '<input type="text" name="width" maxlength="4" class="embed-width">', "<span>&times;</span>", '<input type="text" name="height" maxlength="4" class="embed-height">', "</div>", '<textarea name="output" readonly />', "</div>", "</div>", "</div>"].join("\n");
        this.innerElement = $(e).appendTo(this.domElement),
        this.sizeElement = this.innerElement.find(".size-input"),
        this.socialElement = this.domElement.find(".social")
    },
    createSignals: function() {
        this.closeClicked = new signals.Signal
    },
    addEventListeners: function() {
        this.domElement.on("click", this.onClicked.bind(this)),
        this.domElement.find(".close-button").on("click", this.onCloseClick.bind(this)),
        this.domElement.find("textarea").on("mousedown", this.onEmbedOutputClick.bind(this)),
        this.domElement.find(":radio").on("click focus blur change", this.onEmbedSizeChanged.bind(this)),
        this.domElement.find(".size-input input").on("keydown", this.onBeforeSizeInputChange.bind(this)),
        this.domElement.find(".size-input input").on("change keyup", this.onSizeInputChanged.bind(this))
    },
    populate: function(e) {
        this._super(e),
        this.reset()
    },
    reset: function() {
        this.domElement.find(".radio-group label").removeClass("selected"),
        this.domElement.find(":radio").removeAttr("checked"),
        this.socialElement.empty();
        var e = $('.radio-group label[for="embed-medium"]');
        e.addClass("selected"),
        e.find("input").prop("checked", !0),
        this.embedSize = this.EMBED_MEDIUM
    },
    layout: function() {
        this.domElement.toggleClass("small", QWIKI.player.config.Layout.PLAYER_WIDTH < 440)
    },
    show: function() {
        this.reset(),
        this.writeLink(),
        this.writeEmbed(),
        this._super()
    },
    writeEmbed: function() {
        this.domElement.find("textarea").val(this.generateEmbedCode()),
        this.embedSize === "auto" ? (this.sizeElement.find(".embed-width").val(""), this.sizeElement.find(".embed-height").val("")) : (this.sizeElement.find(".embed-width").val(this.embedSize[0]), this.sizeElement.find(".embed-height").val(this.embedSize[1]))
    },
    writeLink: function() {
        this.socialElement.append('<input class="url" type="text" readonly value="' + this.data.getWatchURL() + '" />'),
        this.socialElement.find(".url").on("click",
        function(e) {
            $(this).focus().select()
        })
    },
    generateEmbedCode: function() {
        var e = "",
        t = [this.data.token];
        this.embedSize !== "auto" && (t[1] = Math.max(this.embedSize[0], this.MINIMUM_SIZE[0]), t[2] = Math.max(this.embedSize[1], this.MINIMUM_SIZE[1]));
        var n = this.data.thumbnail ? '<img src="' + this.data.thumbnail + '" width="40" height="40" style="margin-right: 5px; width: 40px; height: 40px; vertical-align: middle;">': "";
        return e += '<a href="' + this.data.getWatchURL() + '" target="_blank">',
        e += n + " Play the Qwiki: " + this.data.title,
        e += "</a>",
        t = t.join("-"),
        '<iframe src="' + this.data.getEmbedURL() + '" width="' + this.embedSize[0] + '" height="' + this.embedSize[1] + '" scrolling="no" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>'
    },
    onClicked: function(e) {
        e.target === this.domElement.get(0) && this.closeClicked.dispatch()
    },
    onCloseClick: function(e) {
        e.preventDefault(),
        this.closeClicked.dispatch()
    },
    onEmbedOutputClick: function(e) {
        e.preventDefault(),
        this.domElement.find("textarea").focus().select()
    },
    onEmbedSizeChanged: function() {
        var e = this.domElement.find(":radio:checked").val();
        this.domElement.find(".radio-group label").removeClass("selected"),
        this.domElement.find(".radio-group :radio:checked").parent().addClass("selected");
        switch (e) {
        case "small":
            this.embedSize = this.EMBED_SMALL;
            break;
        case "medium":
            this.embedSize = this.EMBED_MEDIUM;
            break;
        case "large":
            this.embedSize = this.EMBED_LARGE;
            break;
        default:
            this.embedSize = "auto"
        }
        this.writeEmbed(),
        this.domElement.find("textarea").focus().select()
    },
    onBeforeSizeInputChange: function(e) {
        var t = e.keyCode,
        n = !!String.fromCharCode(t).match(/[0-9]/g),
        r = t === 8 || t === 9 || t === 46 || t === 17 || t === 18 || t > 36 && t < 41 || e.metaKey; ! n && !r ? e.preventDefault() : this.embedSize === "auto" && (this.embedSize = [0, 0])
    },
    onSizeInputChanged: function(e) {
        var t = parseInt(this.sizeElement.find(".embed-width").val(), 10) || 0,
        n = parseInt(this.sizeElement.find(".embed-height").val(), 10) || 0;
        if (isNaN(t) === !1 || isNaN(n) === !1) {
            var r = $(e.target).attr("name") === "width";
            r ? n = t / this.EMBED_AR: t = n * this.EMBED_AR,
            t = Math.round(t),
            n = Math.round(n),
            r ? n += QWIKI.player.config.Layout.FOOTER_HEIGHT: t -= QWIKI.player.config.Layout.FOOTER_HEIGHT * this.EMBED_AR,
            (this.embedSize[0] !== t || this.embedSize[1] !== n) && t !== 0 && n !== 0 && (this.embedSize[0] = Math.round(Math.max(t, 0)), this.embedSize[1] = Math.round(Math.max(n, 0)), this.writeEmbed(), this.domElement.find(".radio-group label").removeClass("selected"), this.domElement.find(":radio:checked").removeAttr("checked"))
        }
    },
    dispose: function() {
        this._super()
    }
}),
QWIKI.ns("player.components"),
QWIKI.player.components.Video = QWIKI.player.components.Component.extend({
    init: function() {
        this.metadata = {
            width: 0,
            height: 0,
            duration: 0,
            currentTime: 0,
            bufferProgress: 0,
            playbackProgress: 0
        },
        this.updateInterval = -1,
        this._super(),
        this.onSettingsChanged = this.onSettingsChanged.bind(this),
        QWIKI.io.Settings.changed.add(this.onSettingsChanged)
    },
    createDOMElement: function() {
        this._super(),
        this.domElement.addClass("video"),
        this.video = document.createElement("video"),
        this.video.setAttribute("preload", "auto"),
        this.$video = $(this.video),
        this.$video.on("onreadystatechange", this.onReadyStateChange.bind(this)),
        this.$video.on("canplaythrough", this.onCanPlayThrough.bind(this)),
        this.$video.on("loadedmetadata", this.onMetadata.bind(this)),
        this.$video.on("timeupdate", this.onTimeUpdate.bind(this)),
        this.$video.on("canplay", this.onCanPlay.bind(this)),
        this.$video.on("suspend", this.onSuspend.bind(this)),
        this.$video.on("waiting", this.onWaiting.bind(this)),
        this.$video.on("stalled", this.onStalled.bind(this)),
        this.$video.on("error", this.onError.bind(this)),
        this.$video.on("ended", this.onEnded.bind(this)),
        this.$video.on("click", this.onClicked.bind(this)),
        this.$video.on("seeking", this.onSeeking.bind(this)),
        this.$video.on("seeked", this.onSeeked.bind(this)),
        this.$video.appendTo(this.domElement)
    },
    createSignals: function() {
        this.preloaded = new signals.Signal,
        this.error = new signals.Signal,
        this.ended = new signals.Signal,
        this.updated = new signals.Signal,
        this.clicked = new signals.Signal
    },
    load: function() {
        var e = "",
        t = "";
        QWIKI.player.signal.Advisor.isIOS() && (e = this.data.getVideoByType("m3u8").src),
        !e && Modernizr.video.webm && (e = this.data.getVideoByType("webm").src, t = 'video/webm; codecs="vorbis,vp8"'),
        !e && Modernizr.video.h264 && (e = this.data.getVideoByType("mp4").src),
        !e && Modernizr.video.ogg && (e = this.data.getVideoByType("ogg").src),
        !e && this.data.video && this.data.video.outputs && this.data.video.outputs.length && (Modernizr.video.h264 ? e = QWIKI.util.StringUtil.replaceFileExtension(this.data.video.outputs[0], "(mp4|mov|ogg|webm)", "mp4") : Modernizr.video.webm ? e = QWIKI.util.StringUtil.replaceFileExtension(this.data.video.outputs[0], "(mp4|mov|ogg|webm)", "webm") : Modernizr.video.ogg && (e = QWIKI.util.StringUtil.replaceFileExtension(this.data.video.outputs[0], "(mp4|mov|ogg|webm)", "ogg"))),
        e && (this.video.setAttribute("src", e), t && this.video.setAttribute("type", t), QWIKI.player.signal.Advisor.isIOS() && (this.video.play(), this.video.pause()), clearInterval(this.updateInterval), this.updateInterval = setInterval(this.update.bind(this), 1e3 / QWIKI.player.config.Player.FRAMERATE))
    },
    layout: function() {
        this.metadata.loaded && QWIKI.util.DOMUtil.fit(this.$video, this.metadata.width, this.metadata.height, QWIKI.player.config.Layout.PROJECTOR_WIDTH, QWIKI.player.config.Layout.PROJECTOR_HEIGHT, QWIKI.player.data.types.FitType.INSIDE)
    },
    update: function() {
        if (this.metadata.loaded) {
            var e = this.video.currentTime;
            this.state.is(State.PRELOADED) && this.state.toggle(State.BUFFERING, !this.video.paused && this.lastTime === e && this.metadata.duration - e > 1);
            if (this.video.buffered.length > 0) {
                var t = this.video.buffered.end(0),
                n = this.video.duration - .2,
                r = Math.min(t / n, 1);
                this.metadata.bufferProgress += (r - this.metadata.bufferProgress) * .3
            }
            var i = e / this.metadata.duration;
            this.state.is(State.SEEKING) ? this.metadata.playbackProgress = i: this.metadata.playbackProgress += (i - this.metadata.playbackProgress) * .3,
            this.lastTime = e,
            this.updated.dispatch()
        }
    },
    play: function() {
        this.state.set(State.PLAYING),
        this.video.play()
    },
    pause: function() {
        this.state.unset(State.PLAYING),
        this.video.pause()
    },
    seek: function(e) {
        this.video.currentTime = e
    },
    setMuted: function(e) {
        this.video.volume = e ? 0 : 1
    },
    finishPreloading: function() {
        this.domElement.addClass("ready"),
        this.preloaded.dispatch()
    },
    getCurrentTime: function() {
        return this.video.currentTime
    },
    onMetadata: function(e) {
        this.metadata.loaded = !0,
        this.metadata.width = this.video.videoWidth,
        this.metadata.height = this.video.videoHeight,
        this.metadata.duration = this.video.duration,
        this.state.is(State.PRELOADED) && this.finishPreloading()
    },
    onCanPlay: function(e) {
        this.state.is(State.PRELOADED) ? this.state.unset(State.BUFFERING) : (this.state.set(State.PRELOADED), this.setMuted(QWIKI.io.Settings.getValue("mute")), this.metadata.loaded && this.finishPreloading())
    },
    onReadyStateChange: function(e) {},
    onCanPlayThrough: function(e) {},
    onTimeUpdate: function(e) {},
    onSuspend: function(e) {},
    onWaiting: function(e) {
        this.state.set(State.BUFFERING)
    },
    onStalled: function(e) {
        this.state.set(State.BUFFERING)
    },
    onEnded: function(e) {
        this.state.unset(State.PLAYING),
        this.ended.dispatch()
    },
    onError: function(e) {
        this.error.dispatch()
    },
    onSeeking: function(e) {
        this.state.set(State.SEEKING)
    },
    onSeeked: function(e) {
        this.state.unset(State.SEEKING)
    },
    onClicked: function(e) {
        this.clicked.dispatch()
    },
    onSettingsChanged: function(e) {
        this.setMuted(QWIKI.io.Settings.getValue("mute"))
    },
    dispose: function() {
        clearInterval(this.updateInterval),
        QWIKI.io.Settings.changed.remove(this.onSettingsChanged),
        this.video.pause(),
        this.$video.off().attr("src", ""),
        this.preloaded.dispose(),
        this.updated.dispose(),
        this.error.dispose(),
        this.ended.dispose(),
        this.clicked.dispose(),
        this._super()
    }
}),
QWIKI.ns("player.components"),
QWIKI.player.components.VideoFlash = QWIKI.player.components.Component.extend({
    init: function() {
        this.metadata = {
            width: 0,
            height: 0,
            duration: 0,
            bufferProgress: 0,
            playbackProgress: 0
        },
        this.updateInterval = -1,
        this.flashLoadProgressInterval = -1,
        this.flashLoadStartInterval = -1,
        this.flashID = QWIKI.util.StringUtil.uniqueId("flash-video-"),
        this._super(),
        this.onSettingsChanged = this.onSettingsChanged.bind(this),
        QWIKI.io.Settings.changed.add(this.onSettingsChanged)
    },
    createDOMElement: function() {
        this._super(),
        this.domElement.addClass("video"),
        $("<div>").attr("id", this.flashID).appendTo(this.domElement),
        this.clickElement = $('<div class="click-target">').appendTo(this.domElement),
        this.clickElement.on("click", this.onClicked.bind(this))
    },
    createSignals: function() {
        this.preloaded = new signals.Signal,
        this.error = new signals.Signal,
        this.ended = new signals.Signal,
        this.updated = new signals.Signal,
        this.clicked = new signals.Signal
    },
    load: function() {
        this.url = "",
        this.url || (this.url = this.data.getVideoByType("mp4").src),
        this.url || (this.url = this.data.getVideoByType("m4v").src),
        this.url || (this.url = this.data.getVideoByType("flv").src),
        /^http/gi.test(this.url) || (this.url = document.location.protocol + this.url),
        this.url.length === 0 && this.data.video && this.data.video.outputs && (this.url = this.data.video.outputs[0].src);
        var e = {},
        t = {
            allowscriptaccess: "always",
            wmode: "transparent"
        },
        n = {
            id: this.flashID,
            name: this.flashID
        };
        swfobject.embedSWF(QWIKI.player.config.Resources.FLASH_MEDIA_PLAYER, this.flashID, "320", "240", "9", "", e, t, n,
        function(e) {
            e.success ? this.flashLoadStartInterval = setInterval(this.checkFlashLoadStart.bind(this), 100) : this.onVideoLoadError()
        }.bind(this)),
        clearInterval(this.updateInterval),
        this.updateInterval = setInterval(this.update.bind(this), 1e3 / QWIKI.player.config.Player.FRAMERATE)
    },
    checkFlashLoadStart: function() {
        this.video = document[this.flashID] || window[this.flashID],
        this.video && this.video._loadVideo ? ($(this.video).width(QWIKI.player.config.Layout.PROJECTOR_WIDTH).height(QWIKI.player.config.Layout.PROJECTOR_HEIGHT), this.video._loadVideo(this.url), clearInterval(this.flashLoadStartInterval), this.flashLoadProgressInterval = setInterval(this.checkFlashLoadProgress.bind(this), 100)) : Date.now() - this.loadStartTime > QWIKI.player.config.Player.SWF_TIMEOUT && (clearInterval(this.flashLoadStartInterval), this.onVideoLoadError())
    },
    checkFlashLoadProgress: function() {
        this.video._isBroken() ? (clearInterval(this.flashLoadProgressInterval), this.onVideoLoadError()) : Math.min(this.video._getBufferProgress(), 1) === 1 && (clearInterval(this.flashLoadProgressInterval), this.onVideoLoadSuccess())
    },
    layout: function() {
        this.metadata.loaded && $(this.video).width(QWIKI.player.config.Layout.PROJECTOR_WIDTH).height(QWIKI.player.config.Layout.PROJECTOR_HEIGHT)
    },
    update: function() {
        if (this.state.is(State.PRELOADED)) {
            var e = this.getCurrentTime();
            this.state.is(State.PRELOADED) && this.state.toggle(State.BUFFERING, this.state.is(State.PLAYING) && this.lastTime === e);
            var t = e / this.metadata.duration;
            this.metadata.playbackProgress += (t - this.metadata.playbackProgress) * .3,
            this.lastTime = e,
            t > .9999 ? this.onEnded() : (this.state.unset(State.ENDED), this.updated.dispatch())
        }
    },
    play: function() {
        this.state.set(State.PLAYING),
        this.video._play()
    },
    pause: function() {
        this.state.unset(State.PLAYING),
        this.video._pause()
    },
    seek: function(e) {
        this.video._seek(e * 1e3)
    },
    finishPreloading: function() {
        this.domElement.addClass("ready"),
        this.preloaded.dispatch()
    },
    setMuted: function(e) {
        this.video._setVolume(e ? 0 : 1)
    },
    getCurrentTime: function() {
        return this.video._getCurrentTime() / 1e3
    },
    onVideoLoadSuccess: function() {
        this.metadata.loaded = !0,
        this.metadata.width = this.video._getWidth(),
        this.metadata.height = this.video._getHeight(),
        this.metadata.duration = this.video._getDuration() / 1e3,
        this.state.set(State.PRELOADED),
        this.setMuted(QWIKI.io.Settings.getValue("mute")),
        this.finishPreloading()
    },
    onVideoLoadError: function() {
        this.error.dispatch()
    },
    onEnded: function(e) {
        this.state.is(State.ENDED) || (this.state.set(State.ENDED).unset(State.PLAYING), this.ended.dispatch())
    },
    onClicked: function(e) {
        this.clicked.dispatch()
    },
    onSettingsChanged: function(e) {
        this.setMuted(QWIKI.io.Settings.getValue("mute"))
    },
    dispose: function() {
        clearInterval(this.updateInterval),
        clearInterval(this.flashLoadProgressInterval),
        clearInterval(this.flashLoadStartInterval),
        QWIKI.io.Settings.changed.remove(this.onSettingsChanged),
        this.video = null,
        this.preloaded.dispose(),
        this.updated.dispose(),
        this.error.dispose(),
        this.ended.dispose(),
        this.clicked.dispose(),
        this._super()
    }
});